﻿using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using Microsoft.Phone.Tasks;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using WeiboPlus.Shell.ViewModel;
using WeiboPlus.Shell.Events;
using GalaSoft.MvvmLight.Messaging;
using System.Web;

namespace WeiboPlus.Shell.Controls
{
    public class WeiboText : RichTextBox
    {
        public WeiboText()
        {
            this.DefaultStyleKey = base.DefaultStyleKey;
        }

        public static string TAGS = @"(?<URL>(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)"
            + @"|(?<TOPIC>#[^#]+#)|(?<ATME>(?=\s?)@[\w]+(?=\s?))";

        #region Text

        /// <summary>
        /// Text Dependency Property
        /// </summary>
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(WeiboText),
                new PropertyMetadata((string)null,
                    new PropertyChangedCallback(OnTextChanged)));

        /// <summary>
        /// Gets or sets the Text property. This dependency property 
        /// indicates ....
        /// </summary>
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        /// <summary>
        /// Handles changes to the Text property.
        /// </summary>
        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WeiboText target = (WeiboText)d;
            string oldText = (string)e.OldValue;
            string newText = target.Text;
            target.OnTextChanged(oldText, newText);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the Text property.
        /// </summary>
        protected virtual void OnTextChanged(string oldText, string newText)
        {
            if (string.IsNullOrWhiteSpace(newText))
            {
                this.Blocks.Clear();

                return;
            }

            var p = new Paragraph();
            var inlines = p.Inlines;
            var r = null as Run;
            var l = null as Hyperlink;
            var ix = 0;
            var s = string.Empty;
            var rgx = new Regex(TAGS);
            var mcs = rgx.Matches(newText);
            var fb = Application.Current.Resources["PhoneAccentBrush"] as Brush;

            if (mcs.Count > 0)
            {
                foreach (Match i in mcs)
                {
                    if (i.Index > 0 && i.Index > ix)
                    {
                        s = newText.Substring(ix, i.Index - ix);
                        r = new Run { Text = s, };
                        inlines.Add(r);
                    }

                    if (i.Success && i.Length > 0)
                    {
                        s = newText.Substring(i.Index, i.Length);

                        var url = i.Groups["URL"].Value;

                        if (!string.IsNullOrEmpty(url))
                        {
                            l = new Hyperlink { NavigateUri = new Uri(s), Foreground = fb, };
                            l.Click += OnNavigating;
                            r = new Run { Text = s, };
                            l.Inlines.Add(r);
                            inlines.Add(l);
                        }

                        var topic = i.Groups["TOPIC"].Value;

                        if (!string.IsNullOrEmpty(topic))
                        {
                            var url2Q = string.Format("/Views/MainView.xaml?Search={0}",HttpUtility.UrlEncode(topic));

                            l = new Hyperlink { NavigateUri = new Uri(url2Q, UriKind.Relative), Foreground = fb, };
                            l.Click += OnNavigating;
                            r = new Run { Text = s, };                            
                            l.Inlines.Add(r);
                            inlines.Add(l);
                        }

                        var atMe = i.Groups["ATME"].Value;

                        if (!string.IsNullOrEmpty(atMe))
                        {
                            var url2Q = string.Format("/Views/MainView.xaml?Search={0}", atMe);

                            l = new Hyperlink { NavigateUri = new Uri(url2Q, UriKind.Relative), Foreground = fb, };
                            l.Click += OnNavigating;
                            r = new Run { Text = s, };                            
                            l.Inlines.Add(r);
                            inlines.Add(l);
                        }
                    }

                    ix = i.Index + i.Length;
                }

                if (ix < newText.Length - 1)
                {
                    s = newText.Substring(ix, newText.Length - ix);
                    r = new Run { Text = s, };
                    inlines.Add(r);
                }
            }
            else
            {
                r = new Run { Text = newText, };
                inlines.Add(r);
            }

            Blocks.Add(p);
        }

        #endregion

        void OnNavigating(object sender, RoutedEventArgs e)
        {
            var hl = sender as Hyperlink;

            var content = null as string;

            if (hl.Inlines != null && hl.Inlines.Count > 0)
            {
                var r = hl.Inlines[0] as Run;

                if (r != null)
                {
                    content = r.Text;
                }
            }

            var msg = new WeiboTagClickEvent 
            {
                Target = content,
                TargetUri = hl.NavigateUri,
            };

            Messenger.Default.Send<WeiboTagClickEvent>(msg);
        }
    }
}
